﻿using Assets.Scripts.DL.Enemy.BaseClass.FSM;
using JetBrains.Annotations;
using Unity.VisualScripting;
using UnityEngine;

namespace Assets.Scripts.DL.Enemy.BaseClass.Controller {
	public abstract class EnemyControllerBase<EnemyStateEnum>
	: BaseController, IAnimeMgr<EnemyStateEnum>, IRigidBodyMgr {

		protected Animator _animator;
		protected Rigidbody2D _rigidbody;
		protected Collider2D _collider;

		protected IAnimeMgr<EnemyStateEnum> _animeMgr;
		protected IRigidBodyMgr _rigidBodyMgr;

		//protected BaseRayDetect _wallDetect;
		//protected BaseRayDetect _groundDetect;
		//protected BaseRayDetect _playerDetect;
		//protected BaseAtkDetect _atkDetect;


		protected virtual void Awake() {
			_animator = GetComponent<Animator>();
			_rigidbody = GetComponent<Rigidbody2D>();
			_collider = GetComponent<Collider2D>();

		}

		protected abstract void Update();

		public abstract bool CanAtk();


		public abstract bool IsPlayerInAtkRange();

		public abstract bool IsFindPlayer();

		public abstract bool IsOnGround();

		public abstract bool IsTouchingWall();

		public int FaceDir => transform.localScale.x > 0 ? 1 : -1;

		public void ChangeFaceDir(int dir = 0) {
			if (dir == 0) {
				var l = transform.localScale;
				transform.localScale = new Vector3(-l.x, l.y, l.z);
				var v = Velocity;
				Velocity = new Vector2(-v.x, v.y);
			}
			else {
				var l = transform.localScale;
				transform.localScale = new Vector3(dir, l.y, l.z);
			}
		}

		protected bool RayDetect(Vector2 origin, float dis, Vector2 dir, LayerMask layer)
			=> Physics2D.Raycast(origin, dir, dis, layer).collider != null;

		protected Vector2 GetFaceDirVec()
			=> new(transform.localScale.x, 0);

		protected int GetLayer(string layerName)
			=> 1 << LayerMask.NameToLayer(layerName);

		protected abstract void InitStates();

		protected abstract void InitDetects();

		protected abstract void InitAnimMgr();

		protected abstract void InitAtkTimer();


		#region Funcs Of Other AnimMgr
		public void PlayAnim(EnemyStateEnum state) => _animeMgr.PlayAnim(state);

		public void PauseAnim() => _animeMgr.PauseAnim();

		public void ResumeAnim() => _animeMgr.ResumeAnim();

		public void SetAnimPlaySpeed(float speed) => _animeMgr.SetAnimPlaySpeed(speed);

		public bool IsAnimPlayOver(int animLayerIndex = 0) => _animeMgr.IsAnimPlayOver(animLayerIndex);

		public void AddAnim(EnemyStateEnum state, string animName) => _animeMgr.AddAnim(state, animName);

		public bool IsAnimPlayAt(float normalizeTime)
			=> _animeMgr.IsAnimPlayAt(normalizeTime);

		#endregion

		#region RidigBodyMgr

		public Vector2 Velocity { get => _rigidBodyMgr.Velocity; set => _rigidBodyMgr.Velocity = value; }

		public void SetGravity(float gravity) => _rigidBodyMgr.SetGravity(gravity);

		public void ResetGravity() => _rigidBodyMgr.ResetGravity();

		#endregion
	}
}
